const path = require('path');
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const BabiliPlugin = require("babili-webpack-plugin");
const OptimizeCss = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin")
module.exports = {
    //设置环境 development / production
    mode: "production",
    // JS 执行入口文件
    entry: {
        index: './src/js/index.js',
        about: './src/js/about.js',
    },
    // 出口配置
    output: {
        // 把所有依赖的模块合并输出到一个 bundle.js 文件
        filename: "[name].[contenthash:7].js", // 用于长效缓存
        //非入口chunk文件（比如动态加载的文件）名
        chunkFilename: '[id].[chunkhash:7].js',
        // 输出文件都放到 dist 目录下
        path: path.join(__dirname, 'dist'),
        publicPath: "./"
    },
    resolve: {
        //别名
        alias: {
            '@': path.resolve(__dirname, 'src')
        },
        //省略后缀
        extensions: ['.js', '.css', '.scss', '.less']
    },
    //服务设置
    devServer: {
        // 设置服务器访问的基本目录
        contentBase: path.join(__dirname, "dist"),
        //设置服务端压缩
        compress: true,
        //服务器的ip地址 域名
        host: "localhost",
        //直接启动
        open: true,
        //设置端口 默认是8080
        port: 9000
    },
    //模块 加载
    module: {
        rules: [
            {
                test: /\.(jsx|js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node-modules/
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    { loader: "css-loader" }
                ]
            },
            {
                test: /\.(htm|html)$/,
                loader: 'html-withimg-loader'
            },
            {
                test: /\.(png|jpg|svg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 100 * 1024, //单位为bit 10k以内的图片转正base64打包到js中
                            name: '[name]-[contenthash:7].[ext]',//打包文件名
                            esModule: false,
                            outputPath: 'images/'//打包路径
                        }
                    }
                ]

            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1 * 1024, //10k以内的文件转正base64打包到js中
                            // 如果是超过10k 的话，是打包在font的文件下
                            name: '[name]-[contenthash:7].[ext]',//打包文件名
                            outputPath: 'font/'//打包路径
                        }
                    }
                ]
            }
        ]
    },
    // 插件
    plugins: [
        // 清理dist 文件
        new CleanWebpackPlugin(),
        //css 提取
        new MiniCssExtractPlugin({
            filename: "css/[name].[hash:7].css",
            chunkFilename: 'css/[name].[hash:7].css'
        }),
        // HTML模块生成
        new HtmlWebpackPlugin({
            template: './src/html/index.html', // 模板路径 要打包的文件
            filename: 'index.html',//生成的文件名
            // script 标签生成 ，位于哪个地方
            // true 默认 body里， body :body里，head:head里，
            inject: true,
            // 静态资源带hash
            hash: true,
            // 对生成的HTML 文件进行压缩
            minify: {
                //压缩HTML的js
                minifyJS: true,
                //压缩HTML的css
                minifyCSS: true,
                // 删除HTML的注释
                removeComments: true,
                // 去除标签属性的引号
                removeAttributeQuotes: false,
                // 删除空值属性
                removeEmptyAttributes: true,
                //省略布尔值的属性值
                collapseBooleanAttributes: true,
                // 移除type='text/JavaScript' 其他类型属性值保持不变
                removeScriptTypeAttributes: true,
                // 移除type='text/css' 其他类型属性值保持不变
                removeStyleLinkTypeAttributes: true,
                //不要在display：inline的元素之间留下任何空格
                //必须与 collapseWhitespace 一起用
                collapseInlineTagWhitespace: true,
                collapseWhitespace: true
            },
            //主要用于多页面 ，当你有多个入口文件
            // 那就会编译后生成多个打包后的文件
            // 那么chunks 就你选择你要使用的哪些js文件
            // 这些文件会自动添加到生的HTML中
            chunks: ['styles', 'vendor', 'common', 'mainfest', 'index']
        }),
        new HtmlWebpackPlugin({
            template: './src/html/about.html', // 模板路径 要打包的文件
            filename: 'about.html',//生成的文件名
            // script 标签生成 ，位于哪个地方
            // true 默认 body里， body :body里，head:head里，
            inject: true,
            // 静态资源带hash
            hash: true,
            // 对生成的HTML 文件进行压缩
            minify: {
                //压缩HTML的js
                minifyJS: true,
                //压缩HTML的css
                minifyCSS: true,
                // 删除HTML的注释
                removeComments: true,
                // 去除标签属性的引号
                removeAttributeQuotes: false,
                // 删除空值属性
                removeEmptyAttributes: true,
                //省略布尔值的属性值
                collapseBooleanAttributes: true,
                // 移除type='text/JavaScript' 其他类型属性值保持不变
                removeScriptTypeAttributes: true,
                // 移除type='text/css' 其他类型属性值保持不变
                removeStyleLinkTypeAttributes: true,
                //不要在display：inline的元素之间留下任何空格
                //必须与 collapseWhitespace 一起用
                collapseInlineTagWhitespace: true,
                collapseWhitespace: true
            },
            //主要用于多页面 ，当你有多个入口文件
            // 那就会编译后生成多个打包后的文件
            // 那么chunks 就你选择你要使用的哪些js文件
            // 这些文件会自动添加到生的HTML中
            chunks: ['styles', 'vendor', 'common', 'mainfest', 'about']
        }),
        // 复制插件
        new CopyWebpackPlugin(
            { patterns: [{ from: path.join(__dirname, '/src/pubilc'), to: 'pubilc' }] } // 需要拷贝的目录或者路径通配符
        )
    ],
    //提取公共文件
    optimization: {
        //这个表示从哪些chunks里面抽取代码，"initial"（入口文件）|"all" （所有）
        splitChunks: {
            chunks: 'async',
            //限制抽取出来的文件在压缩前最小大小，默认30000
            minSize: 30000,
            //限制抽取出来的文件在压缩前最大大小，默认0，表示不限制最大大小
            maxSize: 0,
            // 表示被引用次数，默认1
            minChunks: 1,
            //最大异步请求数，默认5
            maxAsyncRequests: 5,
            //最大的初始化加载次数，默认3
            maxInitialRequests: 3,
            //抽取出来的文件的自动生成名字的分隔符，默认为~
            automaticNameDelimiter: '~',
            // 抽取出来的文件名字，默认为true，表示自动生成文件名
            name: false,
            // 上面的那么多参数其实都可以不用管，
            // cacheGroups才是关键，它可以继承、覆盖上面splitChunks中所有的参数值
            // 设置缓存组用来抽取满足不同规则的chunk
            cacheGroups: {
                //将所有css 文件打包成一个
                // 注意将权重设置为最高，不然可能其他的cacheGroups会提前打包一部分样式文件
                // priority表示抽取权重，数字越大表示优先级越高，因为一个module可能会满足多个cacheGroups的条件
                styles: {
                    name: 'styles',
                    test: /\.(scss|css|sass|less)$/,
                    chunks: 'all',
                    //如果cacheGroups中没有设置minsize,则据此判断是否使用上层的minsize
                    // true 则是使用0, 0表示不限制大小
                    // false 使用上层minsize
                    enforce: true,
                    priority: 20
                },
                // 第三方库单独打包
                vendor: {
                    name: 'vendor',
                    chunks: 'initial',
                    priority: 10,
                    test: /node_modules/,
                    enforce: true,
                },
                //把所有引入超过1次的模块抽取为cmmon
                common: {
                    name: 'common',
                    chunks: 'initial',
                    priority: 2,
                    minChunks: 2,
                    enforce: true
                }
            }
        },
        //提取manifest,管理模块之间的交互
        runtimeChunk: {
            name: "mainfest"
        },
        //压缩文件
        minimizer: [
            //这是一款基于babel的压缩工具，支持es6的一些特性，取代uglifyJS
            new BabiliPlugin(),
            //压缩css
            new OptimizeCss()
        ]
    }
};